package com.example.demo.thread.future.CompletableFuture;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 *
 * 但是Future对于结果的获取，不是很友好，只能通过阻塞或者轮询的方式得到任务的结果。
 *
 * Future.get() 就是阻塞调用，在线程获取结果之前get方法会一直阻塞。
 * Future提供了一个isDone方法，可以在程序中轮询这个方法查询执行结果。
 * 阻塞的方式和异步编程的设计理念相违背，而轮询的方式会耗费无谓的CPU资源。因此，JDK8设计出CompletableFuture。
 * CompletableFuture提供了一种观察者模式类似的机制，可以让任务执行完成后通知监听的一方。
 *
 *
 * CompletableFuture 异步编程
 *
 * supplyAsync执行CompletableFuture任务，支持返回值
 * runAsync执行CompletableFuture任务，没有返回值。
 *
 *
 * @author luowj12
 * @since 2021/6/16 14:32
 */
public class CompletableFutureTest {

    public static void main(String[] args) throws InterruptedException, TimeoutException, ExecutionException {
        long userId =666L;
        long startTime = System.currentTimeMillis();

        //调用用户服务获取用户基本信息
        CompletableFuture<Integer> completableUserInfoFuture = CompletableFuture.supplyAsync(() -> add1());

        Thread.sleep(300); //模拟主线程其它操作耗时

        CompletableFuture<Integer> completableMedalInfoFuture = CompletableFuture.supplyAsync(() -> add2());

        Integer userInfo = completableUserInfoFuture.get(3, TimeUnit.SECONDS);//获取个人信息结果
        Integer medalInfo = completableMedalInfoFuture.get();//获取勋章信息结果
        System.out.println("总共用时" + (System.currentTimeMillis() - startTime) + "ms");

    }

    public static Integer add1()  {
        int sum = 0;
        for (int i = 0; i < 100; i++) {
            sum += i;
        }
        try {
            Thread.sleep(1000); //模拟调用耗时
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return sum;
    }

    public static Integer add2()  {
        int sum = 0;
        for (int i = 0; i < 100; i++) {
            sum += i;
        }
        try {
            Thread.sleep(2000); //模拟调用耗时
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return sum;
    }

}
